package com.scut.dispatching_server.endpoint;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.scut.dispatching_server.model.Relationship;
import com.scut.dispatching_server.model.Supplier;
import com.scut.dispatching_server.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.logging.Logger;

@ServerEndpoint(value = "/websocket/supplier/{supplierId}")
@Component
public class SupplierEndpoint {

    private static SupplierCache supplierCache;
    private static DemandCache demandCache;
    private static SupplierPost supplierPost;
    private static RelationshipPost relationshipPost;
    private static RelationshipCache relationshipCache;
    private static StatisticsService statisticsService;

    @Autowired
    public void setStatisticsService(StatisticsService statisticsService) {
        SupplierEndpoint.statisticsService = statisticsService;
    }

    @Autowired
    public void setRelationshipCache(RelationshipCache relationshipCache) {
        SupplierEndpoint.relationshipCache = relationshipCache;
    }

    @Autowired
    public void setRelationshipPost(RelationshipPost relationshipPost) {
        SupplierEndpoint.relationshipPost = relationshipPost;
    }

    @Autowired
    public void setDemandCache(DemandCache demandCache) {
        SupplierEndpoint.demandCache = demandCache;
    }
    @Autowired
    public void setSupplierCache(SupplierCache supplierCache) {
        SupplierEndpoint.supplierCache = supplierCache;
    }

    @Autowired
    public void setSupplierPost(SupplierPost supplierPost) {
        SupplierEndpoint.supplierPost = supplierPost;
    }


    private static final Logger sysLogger = Logger.getLogger("sysLog");

    private static Map<String, Session> supplierSessions = new HashMap<>();

    public static Map<String, Session> getSupplierSessions() {
        return supplierSessions;
    }
    @OnOpen
    public void open(Session session,  @PathParam(value = "supplierId")String supplierId) {
        sysLogger.info("open ------ WebSocket opened from sessionId " + session.getId() + " " + supplierId);
        try {
            supplierSessions.put(supplierId, session);
            session.getBasicRemote().sendText("online");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(Session session, String message) throws IOException {
        sysLogger.info("received ***** WebSocket Received from sessionId " + session.getId() + ": " + message);
        JSONObject r = JSON.parseObject(message);
        if(r.get("type").toString().equals("info")){
            Supplier supplier = new Supplier(r.get("id").toString(), Float.parseFloat(r.get("lon").toString()), Float.parseFloat(r.get("lat").toString()));
            supplierCache.saveToCache(supplier);
            supplierCache.addAliveSupplier(supplier.getId());
            supplierPost.addSupplier(supplier);
            return;
        }
        if(r.get("type").toString().equals("select_demand")){
            if (demandCache.deleteDemand(r.get("demand_id").toString())){
                try {
                    session.getBasicRemote().sendText("success");
                    try {
                        DemandEndpoint.getDemandSessions().get(r.get("demand_id").toString()).getBasicRemote().sendText("success");
                        session.getBasicRemote().sendText("success");
                        ArrayList<String> relationships = relationshipCache.getRelationships();
                        for (String relationship : relationships) {
                            String[] ids = relationship.split("-");
                            if (ids[0].equals(r.get("demand_id").toString()) || ids[1].equals(r.get("supplier_id").toString())){
                                relationshipCache.deleteRelationship(relationship);
                            }
                        }
                        relationshipPost.selectRelationship(new Relationship(r.get("demand_id").toString(), r.get("supplier_id").toString()));
                        statisticsService.addSuccessDemands(r.get("demand_id").toString());
                        statisticsService.addAnswerTime((int)(Duration.between(demandCache.getDemand(r.get("demand_id").toString()).getTime(), LocalDateTime.now()).toMillis() / 1000));
                    }
                    catch (IOException e)
                    {
                        sysLogger.info("failed");
                    }
                }
                catch (IOException e) {
                    sysLogger.info("failed");
                }
                supplierCache.deleteSupplier(r.get("supplier_id").toString());
            }
            else {
                try {
                    session.getBasicRemote().sendText("failed");
                }
                catch (IOException e) {
                    sysLogger.info("failed");
                }
            }
            return;
        }
    }

    @OnClose
    public void end(Session session) {
        sysLogger.info("closed XXXXX WebSocket closed from sessionId " + session.getId());
        Collection<Session> sessions = supplierSessions.values();
        sessions.remove(session);
    }


}
